package com.reiuy.service.impl;

import com.reiuy.dao.CartDao;
import com.reiuy.dao.GoodDao;
import com.reiuy.dao.TransactionDao;
import com.reiuy.dao.UserDao;
import com.reiuy.entity.Cart;
import com.reiuy.entity.Good;
import com.reiuy.entity.Transaction;
import com.reiuy.entity.User;
import com.reiuy.exception.BalanceException;
import com.reiuy.exception.TransactionException;
import com.reiuy.service.TransactionService;
import com.reiuy.vo.Transactioninfo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

@Service
public class TransactionServiceImpl implements TransactionService {

    @Resource
    private GoodDao goodDao;

    @Resource
    private UserDao userDao;

    @Resource
    private CartDao cartDao;

    @Resource
    private TransactionDao transactionDao;


    /**
     * 这是用于处理用户直接从shop页面直接发起购买请求
     *
     * @param user     user是一个携带了购买发起者username的对象
     * @param good     good是一个携带了被购买商品的goodid的对象
     * @param quantity 代表购买的数量
     * @return 返回了一个携带了标识数值nums和在数据库中创建的transaction记录的transactionid的map对象
     * 结构类似于{"nums":1/0/-1,"transactionid":transactionid}
     */
    @Override
    public Map<String, Integer> creattransactionbyshop(User user, Good good, Integer quantity) {
        Transaction transaction = new Transaction();
        //创建携带交易内容的transaction对象
        //需要被创建的参数goodid,customerid,quantity,totalprice,transactionstate

        User user_temp;
        user_temp = userDao.selectUesrIdByname(user);
        //通过携带username的user对象拿到携带userid的user对象

        Map<String, Integer> map = new HashMap<>();


        //对用户的购买行为进行判断,用户不被允许购买自己所上传的商品
        if (goodDao.selectSelleridById(good).getSellerid().equals(user_temp.getUserid())) {
            map.put("nums", -1);
            return map;
            //如果用户试图购买自己的商品,则会构成报错,返回-1,作为用户试图购买自己所上传商品的错误标识
        } else {

            transaction.setCustomerid(user_temp.getUserid());
            //将userid作为customerid传入交易对象

            transaction.setGoodid(good.getGoodid());
            //将goodid传入transaction对象

            transaction.setQuantity(quantity);
            //将quantity传入transaction对象

            System.out.println(goodDao.selectPriceById(good).getGoodprice());

            transaction.setTotalprice(quantity * goodDao.selectPriceById(good).getGoodprice());
            //计算出totalprice并传入transaction对象


            transaction.setTransactionstate("未支付");
            //TODO 关于交易的创建这里只进行了第一部分,在第二部分支付过程进行完毕后,会将交易状态变更为支付成功

            System.out.println(transaction.toString());
            int nums = transactionDao.creattransaction(transaction);
            Integer transactionid = transaction.getTransactionid();


            map.put("nums", nums);
            map.put("transactionid", transactionid);
            return map;
        }
    }


    /**
     * 这是由购物车来创建一笔交易的service
     *
     * @param cart cart是一个携带了该条购物车记录的cartid的cart对象
     * @return map由两个kv构成, 一个记载了插入语句影响的条数即nums
     * 另一个记载了插入语句自动增长产生的主键transactionid,用于交易记录的回显;
     */
    @Override
    public Map<String, Integer> creattransactionbycart(Cart cart) {
        Transaction transaction = new Transaction();

        cart = cartDao.selectcartbyid(cart);
        //从网页端只传入用户希望创建为交易的cart的id
        //由这里将其转换为cart中的详细数据并创建为交易
        //TODO 在交易被创建成功后,购物车中的该条记录会被清除,此处尚未完成

        transaction.setGoodid(cart.getGoodid());
        transaction.setCustomerid(cart.getOwnerid());
        transaction.setQuantity(cart.getQuantity());

        Good good = new Good();
        good.setGoodid(cart.getGoodid());
        transaction.setTotalprice(cart.getQuantity() * goodDao.selectPriceById(good).getGoodprice());
        transaction.setTransactionstate("未支付");
        //TODO 关于交易的创建这里只进行了第一部分,在第二部分支付过程进行完毕后,会将交易状态变更为支付成功

        int nums = transactionDao.creattransaction(transaction);
        Integer transactionid = transaction.getTransactionid();

        Map<String, Integer> map = new HashMap<>();
        map.put("nums", nums);
        map.put("transactionid", transactionid);
        return map;
    }


    /**
     * 通过交易id返回交易的细节transactioninfo
     *
     * @param transactionid 交易id
     * @return 该交易id所对应的细节信息info
     */
    @Override
    public Transactioninfo selecttransactioninfoById(Integer transactionid) {
        Transactioninfo transactioninfo = new Transactioninfo();
        Transaction transaction = new Transaction();
        transaction.setTransactionid(transactionid);
        transactioninfo = transactionDao.selecttransactioninfoById(transaction);
        return transactioninfo;
    }

    /**
     * 这是支付的业务方法
     *
     * @param transactionid 需要进行支付的交易id
     * @return 是否成功的布尔类型,其实用void也行,因为抛出异常根本没有return false的机会
     */
    @Transactional(
            rollbackFor = {
                    NullPointerException.class,
                    BalanceException.class
            }
    )
    @Override
    public Boolean dopayment(Integer transactionid) throws TransactionException {
        //本质支付过程是三步
        //1.根据交易的totalprice减少买家的余额
        //2.根据交易的totalprice增加卖家的余额
        //3.上面两步没有问题时,将该笔支付状态修改为已支付,并返回true
        Transaction transaction = new Transaction();
        transaction.setTransactionid(transactionid);
        //新建一个用于储存transactionid的交易对象,并将传入的id放入其中
        Float totalprice = transactionDao.selectTotalById(transactionid);
        //新建一个totalprice变量用于储存该笔交易的交易额


        //第一步
        Integer customerid = transactionDao.selectCustomerId(transaction);
        Float customerbalance = userDao.selectBalanceById(customerid);
        if (customerbalance > totalprice) {
            //余额足够
            totalprice = -totalprice;
            //对于买家来讲这笔交易造成的余额变化为负数
            userDao.updateUserBalance(customerid, totalprice);


            //第二步
            Integer sellerid = transactionDao.selectSellerId(transaction);
            totalprice = -totalprice;
            userDao.updateUserBalance(sellerid,totalprice);

            //第三步
            transaction.setTransactionstate("已支付");
            transactionDao.updatetransactionstate(transaction);
            return true;
        } else {
            throw new BalanceException("余额不足");
        }
    }


    @Override
    public List<Transactioninfo> getUserpaidtransac(String username) {
        User user = new User();
        user.setUsername(username);
        user = userDao.selectUesrIdByname(user);
        List<Transactioninfo> paidtransactioninfos = transactionDao.foundpaidtransac(user);
        return paidtransactioninfos;
    }

    @Override
    public List<Transactioninfo> getUserunpaidtransac(String username) {
        User user = new User();
        user.setUsername(username);
        user = userDao.selectUesrIdByname(user);
        List<Transactioninfo> unpaidtransactioninfos = transactionDao.foundunpaidtransac(user);
        return unpaidtransactioninfos;
    }
}
